define([
    "SzLib", "SzSpin", "angular", "socket.io",
    "jquery", "angular-animate", "angular-bootstrap",
    "angular-route", "angular-route-segment", "angular-scroll-glue"
],
    function (SzLib, SzSpin, angular, io) {
        "use strict";

        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        //- APP
        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        var app = angular.module("Fs2App", [
            "ngAnimate", "ngRoute", "ui.bootstrap",
            "route-segment", "view-segment", "luegg.directives",
            "Fs2App.Controllers", "Fs2App.Services"
        ]);

        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        //- ROUTES
        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        app.config([
            "$routeProvider", "$routeSegmentProvider",
            function($routeProvider, $routeSegmentProvider) {
                $routeSegmentProvider.options.autoLoadTemplates = true;
                $routeSegmentProvider.options.strictMode = true;
                $routeSegmentProvider.
                    // route
                    when("/login",                                  "login").
                    when("/logout",                                 "logout").
                    when("/privilege",                              "privilege").
                    when("/privilege/actor/detail",                 "privilege.actorDetail").
                    when("/privilege/actor/password",               "privilege.actorPassword").
                    when("/privilege/user",                         "privilege.user").
                    when("/privilege/role",                         "privilege.role").
                    when("/privilege/privilege",                    "privilege.privilege").
                    when("/privilege/logger",                       "privilege.logger").
                    when("/data",                                   "data").
                    when("/data/orm/:ormName",                      "data.orm").
                    when("/api",                                    "api").
                    when("/api/module/:moduleName",                 "api.apis").
                    when("/api/module/:moduleName/api/:apiName",    "api.apis.detail").
                    when("/admin",                                  "admin").
                    when("/admin/user",                             "admin.user").
                    when("/admin/user/clear",                       "admin.user.clear").
                    when("/admin/user/cache",                       "admin.user.cache").
                    when("/admin/api",                              "admin.api").
                    when("/admin/script",                           "admin.script").
                    when("/admin/script/flushCocBigOrder",          "admin.script.flushCocBigOrder").
                    when("/admin/script/flushRankingAndJournal",    "admin.script.flushRankingAndJournal").
                    when("/game",                                   "game").
                    when("/game/player",                            "game.player").
                    when("/game/serverStatus",                      "game.serverStatus").
                    when("/game/shareStatus",                       "game.shareStatus").
                    when("/game/player/profile",                    "game.player.profile").
                    when("/game/player/levelUp",                    "game.player.levelUp").
                    when("/game/player/sendItem",                   "game.player.sendItem").
                    when("/game/moreGameStatus",                    "game.moreGameStatus").
                    when("/game/hotPlayStatus",                     "game.hotPlayStatus").
                    when("/game/gmStatus",                          "game.gmStatus").
                    when("/game/noticeStatus",                      "game.noticeStatus").
                    when("/game/operationCache",                    "game.operationCache").
                    when("/game/textScroll",                        "game.textScroll").
                    when("/game/textScroll/insertText",             "game.textScroll.insertText").
                    when("/game/textScroll/checkText",              "game.textScroll.checkText").
                    when("/game/textScroll/deleteText",             "game.textScroll.deleteText").


                    // login
                    segment("login", {
                        "templateUrl": SZ.VIEW_URL + "gm/login.html",
                        "controller": "Fs2LoginCtrl"
                    }).
                    // logout
                    segment("logout", {
                        "templateUrl": SZ.VIEW_URL + "gm/logout.html",
                        "controller": "Fs2LogoutCtrl"
                    }).
                    // privilege
                    segment("privilege", {
                        "templateUrl": SZ.VIEW_URL + "gm/privilege/home.html",
                        "controller": "Fs2PrivilegeCtrl"
                    }).
                    within().
                        segment("actorDetail", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/actor/detail.html",
                            "controller": "Fs2PrivilegeActorCtrl"
                        }).
                        segment("actorPassword", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/actor/password.html",
                            "controller": "Fs2PrivilegeActorCtrl"
                        }).
                        segment("user", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/user/home.html",
                            "controller": "Fs2PrivilegeUserCtrl"
                        }).
                        segment("role", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/role/home.html",
                            "controller": "Fs2PrivilegeRoleCtrl"
                        }).
                        segment("privilege", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/privilege/home.html",
                            "controller": "Fs2PrivilegePrivilegeCtrl"
                        }).
                        segment("logger", {
                            "templateUrl": SZ.VIEW_URL + "gm/privilege/logger/home.html",
                            "controller": "Fs2PrivilegeLoggerCtrl"
                        }).
                    up().
                    // data
                    segment("data", {
                        "templateUrl": SZ.VIEW_URL + "gm/data/home.html",
                        "controller": "Fs2DataCtrl"
                    }).
                    within().
                        segment("orm", {
                            "templateUrl": SZ.VIEW_URL + "gm/data/orm.html",
                            "controller": "Fs2DataOrmCtrl",
                            "dependencies": ["ormName"]
                        }).
                    up().
                    segment("api", {
                        "templateUrl": SZ.VIEW_URL + "gm/api/home.html",
                        "controller": "Fs2ApiCtrl"
                    }).
                    within().
                        segment("apis", {
                            "templateUrl": SZ.VIEW_URL + "gm/api/apis.html",
                            "controller": "Fs2ApiModuleCtrl",
                            "dependencies": ["moduleName"]
                        }).
                        within().
                            segment("detail", {
                                "templateUrl": SZ.VIEW_URL + "gm/api/detail.html",
                                "controller": "Fs2ApiDetailCtrl",
                                "dependencies": ["apiName"]
                            }).
                    up().up().
                    // admin
                    segment("admin", {
                        "templateUrl": SZ.VIEW_URL + "gm/admin/home.html",
                        "controller": "Fs2AdminCtrl"
                    }).
                    within().
                        segment("user", {
                            "templateUrl": SZ.VIEW_URL + "gm/admin/user/home.html",
                            "controller": "Fs2AdminUserCtrl"
                        }).
                        within().
                            segment("clear", {
                                "templateUrl": SZ.VIEW_URL + "gm/admin/user/user.html",
                                "controller": "Fs2AdminUserClearCtrl"
                            }).
                            segment("cache", {
                                "templateUrl": SZ.VIEW_URL + "gm/admin/user/user.html",
                                "controller": "Fs2AdminUserCacheCtrl"
                            }).
                        up().
                        segment("api", {
                            "templateUrl": SZ.VIEW_URL + "gm/admin/api/home.html",
                            "controller": "Fs2AdminApiCtrl"
                        }).
                        segment("script", {
                            "templateUrl": SZ.VIEW_URL + "gm/admin/script/home.html",
                            "controller": "Fs2AdminScriptCtrl"
                        }).
                        within().
                            segment("flushCocBigOrder", {
                                "templateUrl": SZ.VIEW_URL + "gm/admin/script/execute.html",
                                "controller": "Fs2AdminScriptFlushCocBigOrderCtrl"
                            }).
                            segment("flushRankingAndJournal", {
                                "templateUrl": SZ.VIEW_URL + "gm/admin/script/execute.html",
                                "controller": "Fs2AdminScriptFlushRankingAndJournalCtrl"
                            }).
                        up().
                    up().

                    // game
                    segment("game", {
                        "templateUrl": SZ.VIEW_URL + "gm/game/home.html",
                        "controller": "Fs2GameCtrl"
                    }).
                    within().
                        segment("player", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/player/home.html",
                            "controller": "Fs2GamePlayerCtrl"
                        }).
                        within().
                            segment("profile", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/player/profile.html",
                                "controller": "Fs2GamePlayerProfileCtrl"
                            }).
                            segment("levelUp", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/player/levelup.html",
                                "controller": "Fs2GamePlayerLevelUpCtrl"
                            }).
                            segment("sendItem", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/player/sendItem.html",
                                "controller": "Fs2GamePlayerSendItemCtrl"
                            }).
                        up().
                        segment("textScroll", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/textScroll/home.html",
                            "controller": "Fs2GameTextScrollCtrl"
                        }).
                        within().
                            segment("checkText", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/textScroll/checkText.html",
                                "controller": "Fs2GameTextScrollCheckTextCtrl"
                            }).
                            segment("insertText", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/textScroll/insertText.html",
                                "controller": "Fs2GameTextScrollInsertTextCtrl"
                            }).
                            segment("deleteText", {
                                "templateUrl": SZ.VIEW_URL + "gm/game/textScroll/deleteText.html",
                                "controller": "Fs2GameTextScrollDeleteTextCtrl"
                            }).
                        up().




                        segment("serverStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/serverStatus/home.html",
                            "controller": "Fs2GameServerCtrl"
                        }).
                        segment("moreGameStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/moreGameStatus/home.html",
                            "controller": "Fs2MoreGameStatusCtrl"
                        }).
                        segment("hotPlayStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/hotPlayStatus/home.html",
                            "controller": "Fs2HotPlayStatusCtrl"
                        }).
                        segment("gmStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/gmStatus/home.html",
                            "controller": "Fs2GmStatusCtrl"
                        }).
                        segment("noticeStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/noticeStatus/home.html",
                            "controller": "Fs2NoticeStatusCtrl"
                        }).
                        segment("shareStatus", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/shareStatus/home.html",
                            "controller": "Fs2ShareServerCtrl"
                        }).
                        segment("operationCache", {
                            "templateUrl": SZ.VIEW_URL + "gm/game/operationCache/home.html",
                            "controller": "Fs2OperationCacheCtrl"
                        }).
                    up();

                $routeProvider.otherwise({redirectTo: "/privilege"});
            }]);

        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        //- CONTROLLERS
        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        var controllers = angular.module("Fs2App.Controllers", []);

        // Fs2NavCtrl
        controllers.controller("Fs2NavCtrl", [
            "$scope", "$routeSegment",
            function ($scope, $routeSegment) {
                $scope.segment = $routeSegment;
            }]);

        // Fs2ModalCtrl
        controllers.controller("Fs2ModalCtrl", [
            "$scope", "$modalInstance", "Fs2Service",
            function($scope, $modalInstance, service) {
                var scope = service.loadModalScope();
                $scope.action = scope.action; // action: Insert | Edit | Delete
                $scope.pk = scope.pk;
                $scope.type = [];

                // convert possible object data column value to json string
                if (scope.data) {
                    angular.forEach(scope.data, function(value, key) {
                        $scope.type[key] = 'text';
                        if (angular.isObject(value)) {
                            scope.data[key] = angular.toJson(value);
                        }
                    });
                }
                $scope.data = scope.data;

                if (scope.type) {
                    angular.forEach(scope.type, function(value, key){
                        $scope.type[key] = value;
                    });
                }

                $scope.confirm = function(pk, data) {
                    $modalInstance.close({'pk':pk, 'data':data});
                };
                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }
        ]);

        // Fs2LoginCtrl
        controllers.controller("Fs2LoginCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.execute = function(username, password) {
                    if (typeof username === 'undefined') {
                        return; // empty username
                    }
                    if (typeof password === 'undefined') {
                        return; // empty password
                    }
                    password = SzLib.Base64.encode(password);
                    service.post("login", [username, password]).then(function(data) {
                        // load privilege
                        location.hash="#/privilege";
                    });
                };

                $scope.enter = function(ev, username, password) {
                    if (ev.keyCode !== 13) return; // your code
                    $scope.execute(username, password);
                }
            }
        ]);

        // Fs2LogoutCtrl
        controllers.controller("Fs2LogoutCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.post("logout", [], false).then(function(data) {
                    SzLib.log('logout reload!');
                    location.hash="#/login";
                });
            }
        ]);

        // Fs2PrivilegeCtrl
        controllers.controller("Fs2PrivilegeCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function(data) {
                    // show privilege func
                })
            }
        ]);

        // Fs2PrivilegeActorCtrl
        controllers.controller("Fs2PrivilegeActorCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function(data) {
                    $scope.segment = $routeSegment;
                    $scope.data = [];

                    service.post("getActor", [], false).then(function(data) {
                        if (typeof data === "object" && Object.keys(data).length > 0) {
                            $scope.data = {
                                "name": data.name,
                                "email": data.email
                            };
                        }
                    });

                    // 更改我的信息
                    $scope.update = function(data) {
                        service.post("updateActor", [data]).then(function(data) { });
                    };

                    // 更改我的密码
                    $scope.change = function(oldPassword, newPassword) {
                        oldPassword = SzLib.Base64.encode(oldPassword);
                        newPassword = SzLib.Base64.encode(newPassword);
                        service.post("updateActorPassword", [oldPassword, newPassword]).then(function(data) { });
                    };
                })
            }
        ]);

        // Fs2PrivilegeUserCtrl
        controllers.controller("Fs2PrivilegeUserCtrl", [
            "$scope", "$rootScope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $rootScope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    // pagination
                    $scope.dataOnPage = null; // data used to be displayed on page
                    $scope.paginationTotalItems = 0;
                    $scope.paginationCurrentPage = 1;
                    $scope.itemsPerPage = 20;
                    $scope.loadPageData = function(pageNo) {
                        var dataOnPage = [];
                        var startPos = (pageNo - 1) * $scope.itemsPerPage;
                        var endPos = startPos + $scope.itemsPerPage;
                        var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
                        onPageKeys.forEach(function(key) {
                            dataOnPage.push(parseInt(key));
                        });
                        $scope.dataOnPage = dataOnPage;
                    };

                    // data load
                    $scope.dataRows = {}; // data object
                    service.post("getUserList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.dataRows = data;
                            $scope.paginationTotalItems = totalItems;
                            $scope.paginationCurrentPage = 1;
                            app.util.loadPageData(1, $scope);
                        }
                    });

                    // data view
                    var displayedDataPk = null;
                    $scope.dataView = null;
                    $scope.userRole = null;
                    $scope.viewData = function(pk) {
                        $scope.dataView = angular.copy($scope.dataRows[pk]);
                        $scope.dataView.pk = pk;
                        $scope.userRole = $scope.dataView['roleId'];
                        displayedDataPk = pk;
                    };

                    // data filter
                    $scope.filterData = function(filterValue) {
                        if ($scope.dataRows.hasOwnProperty(filterValue)) {
                            $scope.dataView = angular.copy($scope.dataRows[filterValue]);
                        } else {
                            $scope.dataView = null;
                        }
                    };

                    // data insert
                    $scope.insertData = function() {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Create",
                                "pk": null,
                                "data": {'username':null, 'password':null, 'name':null, 'email':null},
                                "type": {'password':'password'} // default type 'text'
                            },
                            function(pkId, data) {
                                service.post("createUser", [data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };

                    // data edit
                    $scope.editData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Edit",
                                "pk": pk,
                                "data": {'name':$scope.dataRows[pk]['name'], 'email':$scope.dataRows[pk]['email']}
                            },
                            function(pkId, data) {
                                service.post("updateUser", [pkId, data]).then(function(result) {
                                    if (!result.hasOwnProperty("succeed") || result.succeed !== true) { return; } // update failed
                                    $scope.dataView = result.data;
                                    $scope.dataView.pk = pk;
                                    $scope.dataRows[pk] = result.data;
                                });
                            }
                        );
                    };

                    // data delete
                    $scope.deleteData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Delete", "pk": pk, "data": angular.copy($scope.dataRows[pk])
                            },
                            function(pkId)
                            {
                                service.post("deleteUser", [pkId]).then(function(result) {
                                    if (result !== true) { return; } // delete failed
                                    if (displayedDataPk === pk) {
                                        $scope.dataView = null;
                                        displayedDataPk = null;
                                    }
                                    delete $scope.dataRows[pk];
                                    $scope.paginationTotalItems -= 1;
                                    app.util.loadPageData($scope.paginationCurrentPage, $scope);
                                });
                            }
                        );
                    };

                    // change Password
                    $scope.updatePassword = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Change Password",
                                "pk": pk,
                                "data": {'oldPassword':null, 'newPassword':null},
                                "type": {'oldPassword':'password', 'newPassword':'password'} // default type 'text'
                            },
                            function(pkId, data) {
                                var oldPassword = SzLib.Base64.encode(data['oldPassword']);
                                var newPassword = SzLib.Base64.encode(data['newPassword']);
                                service.post("updatePassword", [pkId, oldPassword, newPassword]).then(function(result) { });
                            }
                        );
                    };

                    // data load
                    $scope.roleData = {}; // data object
                    service.post("getRoleList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.roleData = data;
                        }
                    });

                    // data delete
                    $scope.updateRole = function(pk) {
                        app.util.openModalDialogue(
                            "changeRole.html", "Fs2UserRoleChooseModalCtrl",
                            $modal, service,
                            {
                                "action": "Choose", "userData": $scope.dataRows[pk], "roleData":$scope.roleData
                            },
                            function(pk, data) {
                                service.post("changeRole", [pk, data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };
                })
            }
        ]);

        // Fs2PrivilegeRoleCtrl
        controllers.controller("Fs2PrivilegeRoleCtrl", [
            "$scope", "$rootScope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $rootScope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    // pagination
                    $scope.dataOnPage = null; // data used to be displayed on page
                    $scope.paginationTotalItems = 0;
                    $scope.paginationCurrentPage = 1;
                    $scope.itemsPerPage = 20;
                    $scope.loadPageData = function(pageNo) {
                        var dataOnPage = [];
                        var startPos = (pageNo - 1) * $scope.itemsPerPage;
                        var endPos = startPos + $scope.itemsPerPage;
                        var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
                        onPageKeys.forEach(function(key) {
                            dataOnPage.push(parseInt(key));
                        });
                        $scope.dataOnPage = dataOnPage;
                    };

                    // data load
                    $scope.dataRows = {}; // data object
                    service.post("getRoleList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.dataRows = data;
                            $scope.paginationTotalItems = totalItems;
                            $scope.paginationCurrentPage = 1;
                            app.util.loadPageData(1, $scope);
                        }
                    });

                    // data view
                    var displayedDataPk = null;
                    $scope.dataView = null;
                    $scope.userRole = null;
                    $scope.viewData = function(pk) {
                        $scope.dataView = angular.copy($scope.dataRows[pk]);
                        $scope.dataView.pk = pk;
                        displayedDataPk = pk;
                    };

                    // data filter
                    $scope.filterData = function(filterValue) {
                        if ($scope.dataRows.hasOwnProperty(filterValue)) {
                            $scope.dataView = angular.copy($scope.dataRows[filterValue]);
                        } else {
                            $scope.dataView = null;
                        }
                    };

                    // data insert
                    $scope.insertData = function() {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Create",
                                "pk": null,
                                "data": {'name':null}
                            },
                            function(pkId, data) {
                                service.post("createRole", [data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };

                    // data edit
                    $scope.editData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Edit",
                                "pk": pk,
                                "data": {'name':$scope.dataRows[pk]['name']}
                            },
                            function(pkId, data) {
                                service.post("updateRole", [pkId, data]).then(function(result) {
                                    if (!result.hasOwnProperty("succeed") || result.succeed !== true) { return; } // update failed
                                    $scope.dataView = result.data;
                                    $scope.dataView.pk = pk;
                                    $scope.dataRows[pk] = result.data;
                                });
                            }
                        );
                    };

                    // data delete
                    $scope.deleteData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Delete", "pk": pk, "data": angular.copy($scope.dataRows[pk])
                            },
                            function(pkId) {
                                service.post("deleteRole", [pkId]).then(function(result) {
                                    if (result !== true) { return; } // delete failed
                                    if (displayedDataPk === pk) {
                                        $scope.dataView = null;
                                        displayedDataPk = null;
                                    }
                                    delete $scope.dataRows[pk];
                                    $scope.paginationTotalItems -= 1;
                                    app.util.loadPageData($scope.paginationCurrentPage, $scope);
                                });
                            }
                        );
                    };

                    // data load
                    $scope.privilegeData = {}; // data object
                    service.post("getPrivilegeList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.privilegeData = data;
                        }
                    });

                    // data delete
                    $scope.changeRolePrivilege = function(pk) {
                        app.util.openModalDialogue(
                            "changeRolePrivilege.html", "Fs2RolePrivilegeChooseModalCtrl",
                            $modal, service,
                            {
                                "action": "Choose", "roleData": $scope.dataRows[pk], "privilegeData":$scope.privilegeData
                            },
                            function(pk, data) {
                                service.post("changeRolePrivilege", [pk, data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };
                })
            }
        ]);

        // Fs2PrivilegePrivilegeCtrl
        controllers.controller("Fs2PrivilegePrivilegeCtrl", [
            "$scope", "$rootScope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $rootScope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    // pagination
                    $scope.dataOnPage = null; // data used to be displayed on page
                    $scope.paginationTotalItems = 0;
                    $scope.paginationCurrentPage = 1;
                    $scope.itemsPerPage = 20;
                    $scope.loadPageData = function(pageNo) {
                        var dataOnPage = [];
                        var startPos = (pageNo - 1) * $scope.itemsPerPage;
                        var endPos = startPos + $scope.itemsPerPage;
                        var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
                        onPageKeys.forEach(function(key) {
                            dataOnPage.push(parseInt(key));
                        });
                        $scope.dataOnPage = dataOnPage;
                    };

                    // data load
                    $scope.dataRows = {}; // data object
                    service.post("getPrivilegeList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.dataRows = data;
                            $scope.paginationTotalItems = totalItems;
                            $scope.paginationCurrentPage = 1;
                            app.util.loadPageData(1, $scope);
                        }
                    });

                    // data view
                    var displayedDataPk = null;
                    $scope.dataView = null;
                    $scope.userRole = null;
                    $scope.viewData = function(pk) {
                        $scope.dataView = angular.copy($scope.dataRows[pk]);
                        $scope.dataView.pk = pk;
                        displayedDataPk = pk;
                    };

                    // data insert
                    $scope.insertData = function() {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Create", "pk": null, "data": {'name':null, 'requestName':null}
                            },
                            function(pkId, data) {
                                service.post("createPrivilege", [data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };

                    // data edit
                    $scope.editData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Edit",
                                "pk": pk,
                                "data": {'name':$scope.dataRows[pk]['name'], 'requestName':$scope.dataRows[pk]['requestName']}
                            },
                            function(pkId, data) {
                                service.post("updatePrivilege", [pkId, data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };

                    // data delete
                    $scope.deleteData = function(pk) {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2ModalCtrl",
                            $modal, service,
                            {
                                "action": "Delete", "pk": pk, "data": angular.copy($scope.dataRows[pk])
                            },
                            function(pkId) {
                                service.post("deletePrivilege", [pkId]).then(function(result) {
                                    if (result !== true) { return; } // delete failed
                                    if (displayedDataPk === pk) {
                                        $scope.dataView = null;
                                        displayedDataPk = null;
                                    }
                                    delete $scope.dataRows[pk];
                                    $scope.paginationTotalItems -= 1;
                                    app.util.loadPageData($scope.paginationCurrentPage, $scope);
                                });
                            }
                        );
                    };

                    // data delete
                    $scope.changePrivilege = function(pk) {
                        app.util.openModalDialogue(
                            "changePrivilege.html", "Fs2PrivilegeChooseModalCtrl",
                            $modal, service,
                            {
                                "action": "Choose", "pk": pk, "privilegeData":$scope.dataRows
                            },
                            function(pk, data) {
                                service.post("changePrivilege", [pk, data]).then(function(result) {
                                    location.reload();
                                });
                            }
                        );
                    };
                })
            }
        ]);

        // Fs2PrivilegeLoggerCtrl
        controllers.controller("Fs2PrivilegeLoggerCtrl", [
            "$scope", "$rootScope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $rootScope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    // pagination
                    $scope.dataOnPage = null; // data used to be displayed on page
                    $scope.paginationTotalItems = 0;
                    $scope.paginationCurrentPage = 1;
                    $scope.itemsPerPage = 20;
                    $scope.loadPageData = function(pageNo) {
                        var dataOnPage = [];
                        var startPos = (pageNo - 1) * $scope.itemsPerPage;
                        var endPos = startPos + $scope.itemsPerPage;
                        var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
                        onPageKeys.forEach(function(key) {
                            dataOnPage.push(parseInt(key));
                        });
                        $scope.dataOnPage = dataOnPage;
                    };

                    $scope.privilegeList = {}; // data object
                    service.post("getPrivilegeList", [], false).then(function(data) {
                        if (typeof data === "object") {
                            $scope.privilegeList = data;
                        }
                    });

                    // data load
                    $scope.dataRows = {}; // data object
                    $scope.getLoggerList = function(actorId) {
                        service.post("getLoggerList", [actorId], false).then(function(data) {
                            if (typeof data === "object") {
                                var totalItems = Object.keys(data).length;
                                if (totalItems <= 0) {
                                    return;
                                }
                                $scope.dataRows = data;
                                $scope.paginationTotalItems = totalItems;
                                $scope.paginationCurrentPage = 1;
                                app.util.loadPageData(1, $scope);
                            } else {
                                $scope.dataRows = {};
                                $scope.paginationTotalItems = 0;
                                $scope.paginationCurrentPage = 1;
                                app.util.loadPageData(1, $scope);
                            }
                        });
                    };

                    // data view
                    var displayedDataPk = null;
                    $scope.dataView = null;
                    $scope.userRole = null;
                    $scope.viewData = function(pk) {
                        $scope.dataView = angular.copy($scope.dataRows[pk]);
                        $scope.dataView.pk = pk;
                        displayedDataPk = pk;
                    };
                })
            }
        ]);

        // Fs2UserRoleChooseModalCtrl
        controllers.controller("Fs2UserRoleChooseModalCtrl", [
            "$scope", "$modalInstance", "Fs2Service",
            function($scope, $modalInstance, service) {
                var scope = service.loadModalScope();
                $scope.action = scope.action; // action: Insert | Edit | Delete
                $scope.userData = scope.userData;
                $scope.checkedRoleId = scope.userData['roleId'];

                $.each(scope.roleData, function(i, val) {
                    if (val['roleId'] === $scope.userData['roleId']) {
                        scope.roleData[i].checked = true;
                    } else {
                        scope.roleData[i].checked = false;
                    }
                });
                $scope.roleData = scope.roleData;


                $scope.choose = function($event) {
                    var checkbox = $event.target;
                    $(".roleId").prop("checked", false);
                    $("#roleId_" + checkbox.value).prop("checked", true);

                    $scope.checkedRoleId = checkbox.value;

                    $.each($scope.roleData, function(i, val) {
                        if (val['roleId'] === checkbox.value) {
                            $scope.roleData[i].checked = true;
                        } else {
                            $scope.roleData[i].checked = false;
                        }
                    });
                };

                $scope.confirm = function() {
                    $modalInstance.close({'pk':$scope.userData['userId'], 'data': $scope.checkedRoleId});
                };
                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }
        ]);

        // Fs2RolePrivilegeChooseModalCtrl
        controllers.controller("Fs2RolePrivilegeChooseModalCtrl", [
            "$scope", "$modalInstance", "Fs2Service",
            function($scope, $modalInstance, service) {
                var scope = service.loadModalScope();
                $scope.action = scope.action; // action: Insert | Edit | Delete
                $scope.roleData = scope.roleData;

                var privilegeIds = jQuery.parseJSON($scope.roleData['privilegeIds']);
                $.each(scope.privilegeData, function(i, val) {
                    if (app.util.in_array(val['privilegeId'], privilegeIds)) {
                        $.each(val['cIds'], function(i, val) {
                            privilegeIds.push(val);
                        });
                        scope.privilegeData[i].checked = true;
                    } else {
                        scope.privilegeData[i].checked = false;
                    }
                });
                $scope.privilegeData = scope.privilegeData;
                $scope.dataOnPage = Object.keys(scope.privilegeData);

                $scope.choose = function(pk, $event) {
                    var checkbox = $event.target;
                    choosePrivilege(pk, checkbox.value, checkbox.checked);
                    chooseChildPrivilege(checkbox.value, checkbox.checked);
                    if (checkbox.checked === false) {
                        chooseParentPrivilege(checkbox.value, checkbox.checked);
                    }
                };

                var choosePrivilege = function (pk, id, checked) {
                    $scope.privilegeData[pk].checked = checked;
                    $(".privilegeId_" + id).prop("checked", checked)
                };

                var chooseChildPrivilege = function (id, checked) {
                    var cIds = jQuery.parseJSON($("#cIds_" + id).val());
                    $.each(cIds, function(i, privilegeId) {
                        var pk;
                        $.each(scope.privilegeData, function(i, val) {
                            if (val['privilegeId'] === privilegeId) {
                                pk = i;
                            }
                        });
                        choosePrivilege(pk, privilegeId, checked);
                        chooseChildPrivilege(privilegeId, checked);
                    });
                };

                var chooseParentPrivilege = function (id, checked) {
                    var cIds = jQuery.parseJSON($("#pIds_" + id).val());
                    $.each(cIds, function(i, privilegeId) {
                        var pk;
                        $.each(scope.privilegeData, function(i, val) {
                            if (val['privilegeId'] === privilegeId) {
                                pk = i;
                            }
                        });
                        choosePrivilege(pk, privilegeId, checked);
                        chooseParentPrivilege(privilegeId, checked);
                    });
                };

                $scope.confirm = function() {
                    var data = [];
                    $.each($scope.privilegeData, function(i, val) {
                        if ($scope.privilegeData[i].checked) {
                            data.push(val['privilegeId']);
                        }
                    });
                    $modalInstance.close({'pk':$scope.roleData['roleId'], 'data':data});
                };
                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }
        ]);

        // Fs2PrivilegeChooseModalCtrl
        controllers.controller("Fs2PrivilegeChooseModalCtrl", [
            "$scope", "$modalInstance", "Fs2Service",
            function($scope, $modalInstance, service) {
                var scope = service.loadModalScope();
                $scope.action = scope.action; // action: Insert | Edit | Delete
                $scope.pk = scope.pk;
                $scope.pkId = scope.privilegeData[scope.pk]['privilegeId'];

                var pkPIds = scope.privilegeData[scope.pk]['pIds'];
                var pkCIds = scope.privilegeData[scope.pk]['cIds'];
                $.each(scope.privilegeData, function(i, val) {
                    scope.privilegeData[i].checked = app.util.in_array(val['privilegeId'], pkPIds);
                    if (app.util.in_array(val['privilegeId'], pkCIds)) {
                        $.each(val['cIds'], function(i, val) {
                            pkCIds.push(val);
                        });
                        scope.privilegeData[i].display = false;
                    } else {
                        scope.privilegeData[i].display = true;
                    }
                });
                $scope.privilegeData = scope.privilegeData;
                $scope.dataOnPage = Object.keys(scope.privilegeData);

                $scope.choose = function(pk, $event) {
                    var checkbox = $event.target;
                    choosePrivilege(pk, checkbox.value, checkbox.checked);
                };

                var choosePrivilege = function (pk, id, checked) {
                    $scope.privilegeData[pk].checked = checked;
                    $(".privilegeId_" + id).prop("checked", checked);
                };

                $scope.confirm = function() {
                    var data = [];
                    $.each($scope.privilegeData, function(i, val) {
                        if ($scope.privilegeData[i].checked) {
                            data.push(val['privilegeId']);
                        }
                    });
                    $modalInstance.close({'pk':$scope.pkId, 'data':data});
                };
                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }
        ]);

        // Fs2DataCtrl
        controllers.controller("Fs2DataCtrl", [
            "$scope", "$routeSegment", "Fs2Service", "Fs2DataService",
            function($scope, $routeSegment, service, dataService) {
                service.checkLoginState().then(function(data) {
                    $scope.segment = $routeSegment;
                    $scope.orms = null;
                    service.post("ormTools", ["loadOrms", []], false).then(function(data) {
                        if (typeof data === "object" && Object.keys(data).length > 0) {
                            dataService.saveOrms(data);
                            $scope.orms = Object.keys(data);
                        }
                    });
                })
            }
        ]);

        // Fs2DataOrmCtrl
        controllers.controller("Fs2DataOrmCtrl", [
            "$scope", "$rootScope", "$routeSegment", "$modal", "Fs2Service", "Fs2DataService",
            function ($scope, $rootScope, $routeSegment, $modal, service, dataService) {
                if (typeof $routeSegment.$routeParams.ormName === 'undefined') {
                    return; // wrong route page
                }
                $scope.ormName = $routeSegment.$routeParams.ormName;
                $scope.Object = Object;

                // pagination
                $scope.dataOnPage = null; // data used to be displayed on page
                $scope.paginationTotalItems = 0;
                $scope.paginationCurrentPage = 1;
                $scope.itemsPerPage = 20;
                $scope.loadPageData = function(pageNo) {
                    var dataOnPage = [];
                    var startPos = (pageNo - 1) * $scope.itemsPerPage;
                    var endPos = startPos + $scope.itemsPerPage;
                    var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
                    onPageKeys.forEach(function(key) {
                        dataOnPage.push(key);
                    });
                    $scope.dataOnPage = dataOnPage;
                };

                // data load
                $scope.dataRows = {}; // data object
                $scope.loadData = function(userId) {
                    if (typeof userId === 'undefined') {
                        return; // empty userId
                    }
                    service.post("ormTools", ["loadOrmData", [userId, $scope.ormName]]).then(function(data) {
                        if (typeof data === "object") {
                            var totalItems = Object.keys(data).length;
                            if (totalItems <= 0) {
                                return;
                            }
                            $scope.dataRows = data;
                            $scope.paginationTotalItems = totalItems;
                            $scope.paginationCurrentPage = 1;
                            $scope.loadPageData(1);
                        }
                    });
                };
                $scope.clear = function() {
                    $scope.userId = null;
                };

                // data view
                var displayedDataPk = null;
                $scope.dataView = null;
                $scope.viewData = function(pk) {
                    $scope.dataView = angular.copy($scope.dataRows[pk]);
                    $scope.dataView.pk = pk;
                    displayedDataPk = pk;
                };

                // data filter
                $scope.filterData = function(filterValue) {
                    if ($scope.dataRows.hasOwnProperty(filterValue)) {
                        $scope.dataView = angular.copy($scope.dataRows[filterValue]);
                    } else {
                        $scope.dataView = null;
                    }
                };

                // data insert
                $scope.insertData = function() {
                    app.util.openModalDialogue(
                        "dataModal.html", "Fs2ModalCtrl",
                        $modal, service,
                        {
                            "action": "Insert", "pk": null, "data": dataService.loadOrmColumns($scope.ormName)
                        },
                        function(data) {
                            service.post("ormTools", ["insertOrmData", [$scope.ormName, data]]).then(function(result) {
                                if (!result.hasOwnProperty("pk") || result.pk === false) { return; } // insert failed
                                $scope.dataRows[result.pk] = result.data;
                                $scope.paginationTotalItems += 1;
                                $scope.loadPageData($scope.paginationCurrentPage);
                            });
                        }
                    );
                };

                // data edit
                $scope.editData = function(pk) {
                    app.util.openModalDialogue(
                        "dataModal.html", "Fs2ModalCtrl",
                        $modal, service,
                        {
                            "action": "Edit", "pk": pk, "data": angular.copy($scope.dataRows[pk])
                        },
                        function(data) {
                            service.post("ormTools", ["updateOrmData", [$scope.ormName, data]]).then(function(result) {
                                if (!result.hasOwnProperty("succeed") || result.succeed !== true) { return; } // update failed
                                $scope.dataRows[pk] = result.data;
                                if (displayedDataPk === pk) {
                                    $scope.dataView = result.data;
                                }
                            });
                        }
                    );
                };

                // data delete
                $scope.deleteData = function(pk) {
                    app.util.openModalDialogue(
                        "dataModal.html", "Fs2ModalCtrl",
                        $modal, service,
                        {
                            "action": "Delete", "pk": pk, "data": angular.copy($scope.dataRows[pk])
                        },
                        function(data) {
                            service.post("ormTools", ["deleteOrmData", [$scope.ormName, data]]).then(function(result) {
                                if (result !== true) { return; } // delete failed
                                if (displayedDataPk === pk) {
                                    $scope.dataView = null;
                                    displayedDataPk = null;
                                }
                                delete $scope.dataRows[pk];
                                $scope.paginationTotalItems -= 1;
                                $scope.loadPageData($scope.paginationCurrentPage);
                            });
                        }
                    );
                };
            }
        ]);


        // Fs2ApiCtrl
        controllers.controller("Fs2ApiCtrl", [
            "$scope", "$routeSegment", "Fs2ApiService",
            function ($scope, $routeSegment, service) {
                $scope.segment = $routeSegment;
                $scope.modules = null;
                service.loadApiModules().then(function(data) {
                    if (typeof data === "object" && Object.keys(data).length > 0) {
                        $scope.modules = data;
                    }
                });
            }
        ]);

        // Fs2ApiModuleCtrl
        controllers.controller("Fs2ApiModuleCtrl", [
            "$scope", "$routeSegment", "Fs2ApiService",
            function ($scope, $routeSegment, service) {
                if (typeof $routeSegment.$routeParams.moduleName === 'undefined') {
                    return; // wrong route page
                }
                $scope.segment = $routeSegment;
                $scope.apis = null;
                $scope.moduleName = $routeSegment.$routeParams.moduleName;
                service.loadModuleApis(
                    $routeSegment.$routeParams.moduleName
                ).then(function(data) {
                    if (typeof data === "object" && Object.keys(data).length > 0) {
                        $scope.apis = data;
                    }
                });
            }
        ]);

        // Fs2ApiDetailCtrl
        controllers.controller("Fs2ApiDetailCtrl", [
            "$scope", "$routeSegment", "Fs2ApiService",
            function ($scope, $routeSegment, service) {
                if (typeof $routeSegment.$routeParams.apiName === 'undefined') {
                    return; // wrong route page
                }
                $scope.paramsInfo = null;
                $scope.apiName = $routeSegment.$routeParams.apiName;
                service.loadApiDetail(
                        $routeSegment.$routeParams.moduleName,
                        $routeSegment.$routeParams.apiName
                    ).then(function(data) {
                        if (typeof data === "object" && Object.keys(data).length > 0) {
                            $scope.paramsInfo = data;
                        }
                    });

                $scope.params = [];
                $scope.apiResponse = null;
                $scope.callApi = function(params) {
                    if (!angular.isObject(params) || Object.keys(params).length === 0) {
                        return; // empty params
                    }
                    // handle params
                    angular.forEach($scope.paramsInfo, function(paramInfo, index) {
                        if (paramInfo.type === "TYPE_JSON") {
                            // convert json type param into json string, then it can be parsed by server
                            params[index] = angular.toJson(params[index]);
                        }
                    });
                    // handle action name
                    var action = $routeSegment.$routeParams.moduleName + '.' + $scope.apiName.slice($routeSegment.$routeParams.moduleName.length);
                    // call api
                    service.callApi(action, params).then(function(data) {
                        if (typeof data === "object" && Object.keys(data).length > 0) {
                            $scope.apiResponse = JSON.stringify(data, null, "\t");
                        }
                    });
                };
                $scope.clear = function() {
                    $scope.params = [];
                };
            }
        ]);

        // Fs2AdminCtrl
        controllers.controller("Fs2AdminCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function(data) {
                    // show privilege func
                })
            }
        ]);

        // Fs2AdminUserCtrl
        controllers.controller("Fs2AdminUserCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
            }
        ]);

        // Fs2AdminUserClearCtrl
        controllers.controller("Fs2AdminUserClearCtrl", [
            "$scope", "$rootScope", "$routeSegment", "Fs2Service",
            function($scope, $rootScope, $routeSegment, service) {
                $scope.name = "清除用户数据";
                $scope.execute = function(userId) {
                    if (typeof userId === 'undefined') {
                        return; // empty userId
                    }
                    if (confirm("确定删除userId:" + userId + "的数据？")) {
                        service.post("deletePlayerGameData", [userId]).then(function(result) {
                            // do nothing
                        });
                    }
                };
                $scope.clear = function() {
                    $scope.userId = null;
                };
            }
        ]);

        // Fs2AdminUserCacheCtrl
        controllers.controller("Fs2AdminUserCacheCtrl", [
            "$scope", "$rootScope", "$routeSegment", "Fs2Service",
            function($scope, $rootScope, $routeSegment, service) {
                $scope.name = "删除用户缓存";
                $scope.execute = function(userId) {
                    if (typeof userId === 'undefined') {
                        return; // empty userId
                    }
                    if (confirm("确定删除userId:" + userId + "的缓存？")) {
                        service.post("deletePlayerCache", [userId]).then(function(result) {
                            // do nothing
                        });
                    }
                };
                $scope.clear = function() {
                    $scope.userId = null;
                };
            }
        ]);

        // Fs2AdminApiCtrl
        controllers.controller("Fs2AdminApiCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.dataView = null; // data object
                $scope.execute = function(params) {
                    if (typeof params === 'undefined') {
                        return; // empty userId
                    }
                    service.postRequest(params).then(function(data) {
                        if (typeof data === "undefined") {
                            $scope.dataView = null;
                        } else {
                            $scope.dataView = data;
                        }
                    });
                };
            }
        ]);

        // Fs2AdminCtrl
        controllers.controller("Fs2GameCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function(data) {
                    // show privilege func
                })
            }
        ]);

        // Fs2GamePlayerCtrl
        controllers.controller("Fs2GamePlayerCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function(data) {
                    $scope.segment = $routeSegment;
                    $scope.data = [];

                    service.post("getActor", [], false).then(function(data) {
                        if (typeof data === "object" && Object.keys(data).length > 0) {
                            $scope.data = {
                                "roleId":data.roleId
                            };
                        }
                    });
                })
            }
        ]);

        // Fs2GameServerCtrl
        controllers.controller("Fs2GameServerCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleServerStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        // Fs2MoreGameStatusCtrl
        controllers.controller("Fs2MoreGameStatusCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleMoreGameStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        // Fs2HotPlayStatusCtrl
        controllers.controller("Fs2HotPlayStatusCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleHotPlayStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        // Fs2GmStatusCtrl
        controllers.controller("Fs2GmStatusCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleGmStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        // Fs2NoticeStatusCtrl
        controllers.controller("Fs2NoticeStatusCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleNoticeStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        //  Fs2ShareServerCtrl
        controllers.controller("Fs2ShareServerCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus = function (handle, msg) {
                        service.post("handleShareStatus", [handle, msg]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        //  Fs2OperationCacheCtrl
        controllers.controller("Fs2OperationCacheCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                service.checkLoginState().then(function (date) {
                    $scope.dataView = null; // data object
                    $scope.serverStatus12 = function (handle, cacheKey, uId) {
                        service.post("handleOperationCache", [handle, cacheKey, uId]).then(function (data) {
                            $scope.dataView = data;
                        });
                    }
                });
            }
        ]);

        // Fs2GamePlayerProfileCtrl
        controllers.controller("Fs2GamePlayerProfileCtrl", [
            "$scope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {

                    $scope.profileInfoName = {
                        "0":"平台ID", "1":"语言版本", "2":"花镇名称", "3":"国籍ID", "4":"头像ID",
                        "6":"解锁地块", "10":"收银台金币", "12":"建筑订单完成数", "21":"行动点",
                        "30":"点赞总和数量", "31":"当期点赞数量", "32":"当天点赞数量", "33":"点赞重置时间",
                        "34":"点赞奖励道具", "35":"点赞奖励数量", "36":"点赞奖励发放总数", "37":"今日点赞玩家",
                        "40":"商会ID", "41":"商会邀请", "42":"商会退出时间", "50":"植物种植的积分",
                        "51":"订单完成数量", "52":"生产产品积分", "53":"花艺生产积分", "54":"火车订单数量",
                        "55":"花架金币收集", "56":"声望建筑订单完成", "57":"商铺金币收集", "60":"排行榜期数",
                        "61":"已接到任务", "62":"帮忙浇水复活次数", "63":"成就积分", "64":"成就积分已领奖励",
                        "65":"已完成收集", "66":"已完成成就", "69":"礼券", "70":"公会币",
                        "71":"收集币", "72":"飞机票", "73":"额外掉落表", "74":"行为计数",
                        "75":"新手引导信息", "76":"帮助浇水的玩家", "77":"商铺每日经验", "78":"自动点赞时间",
                        "99":"数据中心gameId", "100":"GM系统邮件", "101":"充值的总金额", "102":"注册ip",
                        "103":"登录ip", "104":"平台信息", "105":"已打补丁", "106":"已领礼包批次",
                        "107":"新手订单板进度", "108":"新手火车订单板进度", "109":"新手豪华火车订单板进度", "110":"手游下载奖励状态",
                        "111":"观看感谢信", "112":"帮助摇钱树的好友", "113":"飞机票下次自动恢复时间",
                    };

                    // data load
                    $scope.dataView = null; // data object
                    $scope.loadPlayerData = function(userId) {
                        service.post("loadPlayerData", [userId]).then(function(data) {
                            if (typeof data === "object") {
                                var totalItems = Object.keys(data).length;
                                if (totalItems <= 0) {
                                    return;
                                }
                                $scope.dataView = data;
                            }
                        });
                    };

                    // data edit
                    $scope.editPlayerData = function() {
                        app.util.openModalDialogue(
                            "dataModal.html", "Fs2GameUserProfileModalCtrl",
                            $modal, service,
                            {
                                "pk": $scope.dataView.profile.userId,
                                "profile": angular.copy($scope.dataView.profile),
                                "payment": angular.copy($scope.dataView.payment),
                                "profileInfoList": angular.copy($scope.dataView.profileInfoList),
                                "profileInfoName": angular.copy($scope.profileInfoName)
                            },
                            function(pkId, data) {
                                service.post("editPlayerData", [pkId, data]).then(function(result) {
                                    $scope.dataView = result;
                                });
                            }
                        );
                    };
                })
            }
        ]);

        // Fs2GameUserProfileModalCtrl
        controllers.controller("Fs2GameUserProfileModalCtrl", [
            "$scope", "$modalInstance", "Fs2Service",
            function($scope, $modalInstance, service) {
                var scope = service.loadModalScope();
                $scope.pk = scope.pk;

                var profileColumns = {};
                $.each(scope.profile, function(i, val) {
                    if (app.util.in_array(i, ['energy', 'exp', 'freeToken'])) {
                        profileColumns[i] = val;
                    }
                });
                $scope.profile = profileColumns;

                var paymentColumns = {};
                $.each(scope.payment, function(i, val) {
                    if (app.util.in_array(i, ['bonusMoney'])) {
                        paymentColumns[i] = val;
                    }
                });
                $scope.payment = paymentColumns;

                var profileInfoColumns = {};
                $.each(scope.profileInfoList, function(i, val) {
                    if (app.util.in_array(i, [1, 2, 3, 4, 7, 10, 12, 13, 15])) {
                        profileInfoColumns[i] = val.info;
                    }
                });
                $scope.profileInfoList = profileInfoColumns;
                $scope.profileInfoName = scope.profileInfoName;

                $scope.confirm = function(pk, profile, payment, profileInfoList) {
                    var data = {};
                    data['profile'] = profile;
                    data['payment'] = payment;
                    data['profileInfoList'] = profileInfoList;
                    $modalInstance.close({'pk':pk, 'data':data});
                };
                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }
        ]);

        // Fs2GamePlayerLevelUpCtrl
        controllers.controller("Fs2GamePlayerLevelUpCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.execute = function(userId, level) {
                    service.post("updatePlayerLevel", [userId, level]).then(function(data) {
                        // do nothing
                    });
                };
            }
        ]);

        // Fs2GamePlayerSendItemCtrl
        controllers.controller("Fs2GamePlayerSendItemCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.execute = function(userId, itemDefId, count) {
                    service.post("sendItem", [userId, itemDefId, count]).then(function(data) {
                        // do nothing
                    });
                };
                $scope.reduceItem =  function(userId, itemDefId, count) {
                    service.post("reduceItem", [userId, itemDefId, count]).then(function (data) {
                        // do nothing
                    });
                };
            }
        ]);

        // Fs2AdminScriptCtrl
        controllers.controller("Fs2AdminScriptCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
            }
        ]);

        // Fs2AdminScriptFlushCocBigOrderCtrl
        controllers.controller("Fs2AdminScriptFlushCocBigOrderCtrl", [
            "$scope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    $scope.execute = function(password) {
                        service.post("handleScript", ['flushCocBigOrderCtrl', password]).then(function(result) {
                            SzLib.log(result);
                        });
                    };
                })
            }
        ]);

        // Fs2AdminScriptFlushRankingAndJournalCtrl
        controllers.controller("Fs2AdminScriptFlushRankingAndJournalCtrl", [
            "$scope", "$routeSegment", "$modal", "Fs2Service",
            function($scope, $routeSegment, $modal, service) {
                service.checkLoginState().then(function(data) {
                    $scope.execute = function(password) {
                        service.post("handleScript", ['flushRankingAndJournal', password]).then(function(result) {
                            SzLib.log(result);
                        });
                    };
                })
            }
        ]);

        // Fs2GameTextScrollCtrl
        controllers.controller("Fs2GameTextScrollCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
            }
        ]);

        // Fs2GameTextScrollCheckTextCtrl
        controllers.controller("Fs2GameTextScrollCheckTextCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.dataView = null; // data object
                $scope.checkTextScroll = function() {
                    service.post("checkTextScroll", [1]).then(function (data) {
                        $scope.dataView = data.textScroll;
                    });
                }
            }
        ]);

        // Fs2GameTextScrollInsertTextCtrl
        controllers.controller("Fs2GameTextScrollInsertTextCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.insertTextScroll = function(textId, content, type, start,interval, end) {
                    service.post("insertTextScroll", [textId, content, type, start,interval, end]).then(function(data) {
                        // do nothing
                    });
                };
            }
        ]);
        // Fs2GameTextScrollDeleteTextCtrl
        controllers.controller("Fs2GameTextScrollDeleteTextCtrl", [
            "$scope", "$routeSegment", "Fs2Service",
            function($scope, $routeSegment, service) {
                $scope.deleteTextScroll = function(tid) {
                    service.post("deleteTextScroll", [tid]).then(function(data) {
                        // do nothing
                    });
                };
            }
        ]);

        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        //- SERVICES
        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        var services = angular.module("Fs2App.Services", []);

        // Fs2ApiService
        services.factory("Fs2ApiService", ["$http", "$q", function($http, $q) {
            /**
             * {
         *     moduleName: {
         *         apiName: [
         *             0: {
         *                 "name": paramName,
         *                 "type": paramType
         *             },
         *             ...
         *         ],
         *         ...
         *     },
         *     ...
         * }
             */
            var apiData = null;

            var loadApiModules = function() {
                var deferred = $q.defer();
                var onSuccess = function(result) {
                    if (app.util.handleResponse(result, false)) { // {moduleName: {}, ...}
                        apiData = result.msg[0];
                        deferred.resolve(Object.keys(apiData));
                    } else {
                        deferred.reject();
                    }
                };

                app.util.post($http, $q, "apiTools", ["loadApiModules", []], false, onSuccess)
                return SzSpin.run(deferred.promise);
            };

            var loadModuleApis = function(moduleName) {
                var deferred = $q.defer();
                var onSuccess = function(result) {
                    if (app.util.handleResponse(result, false)) { // {apiName: [], ...}
                        apiData[moduleName] = result.msg[0];
                        deferred.resolve(Object.keys(apiData[moduleName]));
                    } else {
                        deferred.reject();
                    }
                };

                app.util.post($http, $q, "apiTools", ["loadModuleApis", [moduleName]], false, onSuccess)
                return SzSpin.run(deferred.promise);
            };

            var loadApiDetail = function(moduleName, apiName) {
                var deferred = $q.defer();
                var onSuccess = function(result) {
                    if (app.util.handleResponse(result, false)) { // [0: {"name": paramName, "type": paramType}, ...]
                        apiData[moduleName][apiName] = result.msg[0];
                        deferred.resolve(apiData[moduleName][apiName]);
                    } else {
                        deferred.reject();
                    }
                };

                app.util.post($http, $q, "apiTools", ["loadApiDetail", [moduleName, apiName]], false, onSuccess)
                return SzSpin.run(deferred.promise);
            };

            var callApi = function(apiName, params) {
                if (SZ.IS_COMPRESS) {
                    params = SzLib.compress([[apiName, params]], true);
                } else {
                    params = [[apiName, params]];
                }

                var deferred = $q.defer();
                $http({
                    method: "POST",
                    url: SZ.REQUEST_URL,
                    data: $.param({
                        "token": "52d0ee3c031dd",
                        "*": params
                    }),
                    headers: {"Content-type": "application/x-www-form-urlencoded"}
                }).success(function(result) {
                    if (SZ.IS_COMPRESS) {
                        result = SzLib.decompress(result, true);
                    }
                    if (app.util.handleResponse(result, true)) {
                        deferred.resolve(result.msg[0]);
                    } else {
                        deferred.reject();
                    }
                });
                return SzSpin.run(deferred.promise);
            };

            return {
                "loadApiModules": loadApiModules,
                "loadModuleApis": loadModuleApis,
                "loadApiDetail": loadApiDetail,
                "callApi": callApi
            };
        }]);

        services.factory("Fs2Service", ["$http", "$q", function($http, $q) {
            var modalScope = {};
            var saveModalScope = function(scope) {
                modalScope = scope;
            };

            var loadModalScope = function() {
                return modalScope;
            };

            var post = function(api, data, showMsg, onSuccess) {
                return app.util.post($http, $q, api, data, showMsg, onSuccess);
            };

            var checkLoginState = function() {
                return app.util.post($http, $q, "checkLoginState", [], false, function(result) {
                    if (angular.isObject(result) && result.hasOwnProperty("code") && result.code === 0) {
                        $('#logout-button').removeClass('hide');
                    } else {
                        location.hash="#/login";
                    }
                });
            };

            var postRequest = function(params) {
                var deferred = $q.defer();
                $http({
                    method: "POST",
                    url: SZ.REQUEST_URL,
                    data: $.param({
                        "token": "52d0ee3c031dd",
                        "*": params
                    }),
                    headers: {"Content-type": "application/x-www-form-urlencoded"}
                }).success(function(result) {
                    if (SZ.IS_COMPRESS) {
                        result = SzLib.decompress(result, true);
                    }
                    if (typeof onSuccess !== 'undefined') {
                        onSuccess(result)
                    }
                    if (app.util.handleResponse(result, true)) {
                        deferred.resolve(result.msg[0]);
                    } else {
                        deferred.reject();
                    }
                });
                return SzSpin.run(deferred.promise);
            };

            return {
                "saveModalScope" : saveModalScope,
                "loadModalScope" : loadModalScope,
                "post" : post,
                "checkLoginState" : checkLoginState,
                "postRequest" : postRequest
            }
        }]);

        services.factory("Fs2DataService", ["$http", "$q", function($http, $q) {
            var ormData = null;

            var saveOrms = function(data) {
                ormData = data;
            };

            var loadOrmColumns = function(ormName) {
                return angular.copy(ormData[ormName]);
            };

            return {
                "saveOrms": saveOrms,
                "loadOrmColumns": loadOrmColumns
            };
        }]);

        services.factory("Fs2GameService", ["$http", "$q", function($http, $q) {

        }]);

        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        //- GLOBAL UTIL
        //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
        var AdminUtil = function() {
            // add msg box parent
            $(document.body).append('<div id="msg-mask" style="display:none;position:fixed;top:50%;right:0;width:50%;z-index:10000;"></div>');
        };

        AdminUtil.prototype.loadPageData = function(pageNo, $scope) {
            var dataOnPage = [];
            var startPos = (pageNo - 1) * $scope.itemsPerPage;
            var endPos = startPos + $scope.itemsPerPage;
            var onPageKeys = Object.keys($scope.dataRows).slice(startPos, endPos);
            onPageKeys.forEach(function(key) {
                dataOnPage.push(parseInt(key));
            });
            $scope.dataOnPage = dataOnPage;
        };

        AdminUtil.prototype.openModalDialogue = function(templateUrl, controller, $modal, service, scope, confirmCallback) {
            service.saveModalScope(scope);
            var modalInstance = $modal.open({
                "templateUrl": templateUrl,
                "controller": controller
            });
            modalInstance.result.then(function(result) {
                confirmCallback(result.pk, result.data);
            }, function () {
                SzLib.log("Modal dialogue cancelled, action: " + scope.action + ", pk: " + scope.pk + ", data: " + angular.toJson(scope.data));
            });
        };

        AdminUtil.prototype.post = function($http, $q, reqName, reqParams, showMsg, onSuccess) {
            var deferred = $q.defer();
            $http({
                method: "POST",
                url: SZ.REQUEST_URL,
                data: app.util.buildAdminReqParams(reqName, reqParams),
                headers: {"Content-type": "application/x-www-form-urlencoded"}
            }).success(function(result) {
                if (SZ.IS_COMPRESS) {
                    result = SzLib.decompress(result, true);
                }
                if (typeof onSuccess !== 'undefined') {
                    onSuccess(result)
                }
                if (app.util.handleResponse(result, showMsg)) {
                    deferred.resolve(result.msg[0]);
                } else {
                    deferred.reject();
                }
            });
            return SzSpin.run(deferred.promise);
        };

        AdminUtil.prototype.buildReqParams = function(action, params) {
            var user_id = params[0];
            if (SZ.IS_COMPRESS) {
                params = SzLib.compress([[action, params]], true);
            } else {
                params = [[action, params]];
            }
            return $.param({
                "pf_token": "52d0ee3c031dd",
                "token": "52d0ee3c031dd",
                "user_id": user_id, // the first param shall always be "userId"
                "*": params
            });
        };

        AdminUtil.prototype.buildAdminReqParams = function(reqName, reqParams) {
            var reqData = [reqName];
            if (typeof reqParams == "object" && Object.keys(reqParams).length > 0) {
                reqData.push(angular.toJson(reqParams));
            }
            var params;
            if (SZ.IS_COMPRESS) {
                params = SzLib.compress([["gm.index", reqData]], true);
            } else {
                params = [["gm.index", reqData]];
            }
            return $.param({
                "token": "52d0ee3c031dd",
                "*": params
            });
        };

        AdminUtil.prototype.handleResponse = function(result, showMsg) {
            if (typeof showMsg !== "boolean") {
                showMsg = true;
            }
            if (angular.isObject(result) && result.hasOwnProperty("code") && result.code !== 0) {
                // request failed with normal framework exception
                if (showMsg) { // show failure msg box
                    this.showMessageBox("REQ Failed: [" + result.code + "] " + JSON.stringify(result.msg), "alert-danger");
                }
                return false;
            } else if (!angular.isObject(result)
                || (angular.isObject(result) && !result.hasOwnProperty("code"))
                ) {
                // request failed without normal framework exception
                if (showMsg) { // show failure msg box
                    this.showMessageBox("REQ Failed!", "alert-danger");
                }
                return false;
            } else {
                // request done
                if (showMsg) { // show success msg box, and hide automatically
                    this.showMessageBox("REQ Succeed!");
                }
                return true;
            }
        };

        AdminUtil.prototype.showMessageBox = function(msg, type) {
            if (typeof msg == "object") {
                msg = angular.toJson(msg);
            }
            if (!angular.isString(type)
                || (type != "alert-success" && type != "alert-info"
                && type != "alert-warning" && type != "alert-danger")) {
                type = "alert-success";
            }
            var box = '<div id="msgBox" class="alert ' + type + ' alert-dismissable">' +
                '<button type="button" class="close" data-dismiss="alert" onclick="SZ.APP.util.hideMsgMask();">&times;</button>' +
                '<span>' + msg + '</span>' +
                '</div>';

            $("#msg-mask").append(box).show();
            if (type != "alert-danger") { // if not error message, hide automatically
                setTimeout(function() {
                    $("#msgBox").fadeOut(500, function(){ $("#msgBox").remove(); $("#msg-mask").hide(); });
                }, 1500);
            }
        };

        AdminUtil.prototype.hideMsgMask = function() {
            var mask = $("#msg-mask");
            if (mask.children().length <= 0) {
                mask.hide();
            }
        };

        AdminUtil.prototype.in_array = function(stringToSearch, arrayToSearch) {
            for (var s = 0; s < arrayToSearch.length; s++) {
                var thisEntry = arrayToSearch[s].toString();
                if (thisEntry == stringToSearch) {
                    return true;
                }
            }
            return false;
        };

        app.util = new AdminUtil();

        return app;
    });